package work.chenxr.idempotency.aspect;

import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import work.chenxr.idempotency.annotations.Idempotency;
import work.chenxr.idempotency.cache.RedisCache;
import work.chenxr.idempotency.utils.HttpContextUtil;
import work.chenxr.idempotency.utils.IpUtil;

/**
 * @Author Chenxr
 * @Date 2023/10/24
 * @Description 幂等切面
 */
@Aspect
@Component
@AllArgsConstructor
public class IdempotencyAspect {
    private final RedisCache redisCache;

    @Pointcut(value = "@annotation(work.chenxr.idempotency.annotations.Idempotency)")
    public void idempotencyPointCut() {
    }

    @Before(value = "idempotencyPointCut() && @annotation(idempotency)")
    public void before(Idempotency idempotency) {
        HttpServletRequest request = HttpContextUtil.getHttpServletRequest();
        assert request != null;
        String key = this.getIdempotentKey(IpUtil.getIpAddr(request) + ":"
                + this.getUserId() + request.getRequestURI().replace("/", ":"));
        Object count = redisCache.get(key);
        if (ObjectUtils.isNotEmpty(count)) {
            if (Integer.parseInt(count.toString()) >= idempotency.count()) {
                // 这里应该抛出自定义异常，拦截异常后应该返回给前端JSON格式响应
                throw new RuntimeException("您点击的太快了，休息一下");
            }
            redisCache.set(key, (int) count + 1, idempotency.time());
        } else {
            redisCache.set(key, 1, idempotency.time());
        }
    }

    private String getIdempotentKey(String userUrl) {
        return "idempotent:" + userUrl;
    }

    /**
     * 获取用户ID，接入安全框架后自行实现，这里只是示例
     */
    private String getUserId() {
        return "10000";
    }
}
